var wikid = wikid || {};

/**
 * Extract the couch db from the url
 */
wikid.parseDBname = function(url) {
	var match = /\/_(\w+)\//.exec(url);
    var db_name = match[1];
	return db_name;
}

/*
 * Gets the topic name from the url
*/
wikid.parseTopicName = function(url) {
	var match = /\?(\w+)(#.+)?$/.exec(url);
	if (match) {
		var db_name = match[1];
		return db_name;	
	} else {
		var querystr = /\?(.+)$/.exec(url);
        if (!querystr) return null;
        querystr = querystr[1];
		var query_vars = $.parseQuery(querystr);
		if (!query_vars.name) {
			// find the param with no value
			var db_name;
			jQuery.each(query_vars, function(name, val) {	
				if (val == "undefined") {
					db_name = name;
				}
			});
			return db_name;
		}
		else return query_vars.name;
	}
}

/**
* Turn an id into a Human readable name
* so Test_Name becomes Test Name
*/
wikid.titleFromTopicId = function(topicId) {
	return topicId.replace(/_/g," ");
}

wikid.topicIdFromTitle = function(title) {
    return title.replace(/ /g,"_");
}

wikid.parseTagsToAdd = function(url) {
	var querystr = /\?(.+)$/.exec(url);
    if (!querystr) return [];
    querystr = querystr[1];
	var query_vars = $.parseQuery(querystr);
	var tags = query_vars.tags;
	if (!tags) {
		tags = query_vars['new'];
	} else if (query_vars['new']){
		jQuery.merge(tags, query_vars['new']);
	}
	if (!tags) return [];
	return tags.split(",");
}


wikid.parseNewTags = function(url) {
	var querystr = /\?(.+)$/.exec(url)[1];
	var query_vars = $.parseQuery(querystr);
	var tags = query_vars['new'];
	if (!tags) return [];
	return tags.split(",");
}


/**
* Uses the modified showdown converter to create the html from the wiki text
* the ref is an object that can be refrenced in the wiki text by [-path].
* We also now pass the db_name
*/
wikid.wikiTextToHtml = function(text, ref, db_name) {
	var converter = new Showdown.converter();
	return converter.makeHtml(text, ref, db_name);
}

/**
* Generate the href and alias for a tag
*/
wikid.getTagLink = function(tag) {
	var link = {};
	link.href  = "topic.html?" + tag;
	link.alias =  this.titleFromTopicId(tag);
	return link;
}

wikid.getTagLinkJqNode = function(tag) {
    var link = wikid.getTagLink(tag);
    return $('<a href="' + link.href + '">' + link.alias + '</a>');
}

wikid.getTagEditHref = function(tag, createInstance) {
    if (createInstance)
        return "edit.html?new=" + tag ;
    else
        return "edit.html?tags=" + tag ;
}



wikid.addTrayItem = function(tag, tray) {
    var trayItem = $('<div class="trayItem" ></div>');
    tray.append(trayItem);
    trayItem.append(wikid.getTagLinkJqNode(tag));

    var add = $('<button class="add" title="New"></button>').button({
        icons: { primary: 'ui-icon-plus'},
        text: false

      })
      .click(function() {
         var url = wikid.getTagEditHref(tag,  false);
        window.location = url;
         return false;
     });
    trayItem.append(add);
    //add.find('span').css('left', '0px');

    return trayItem;
}

wikid.createTray = function(db, traySelector) {
    var settings = db.open('-settings');
    if (!settings) {
        settings = {
            _id:"-settings",
            tray:["Person","Project","Action_Item"]
        };
        db.save(settings);
    }
    if (settings.tray) {
      var tray = $(traySelector);
      $.each(settings.tray, function(i, tag) {
          wikid.addTrayItem(tag, tray);
      }) ;
    }
}



wikid.createDragToTray = function(db, dragSelector, traySelector) {
    var currentDragged = null;;

    var createDrag = function() {

        $(dragSelector).draggable({
            handle: 'span',
            opacity: 0.7,
            helper: 'clone',
            start: function(event, ui) {
                currentDragged = ui.helper.prevObject.attr('title');
            },
            stop : function(event, ui) {
                currentDragged = null;
            }
        });
        $(dragSelector).find('span.ui-icon')
           .css('display', 'inline-block')
           .css('cursor', 'move');
    }
    setTimeout(createDrag, 2);

    var tray = $(traySelector);
    tray.mouseenter(function(){
        if (currentDragged) {
            $(this).addClass('ui-state-highlight');

            var item = wikid.addTrayItem(currentDragged, tray);
            item.addClass('tempTrayItem');
        }
    }).mouseleave(function() {
        if (currentDragged) {
            $(this).removeClass('ui-state-highlight');
            $('.tempTrayItem').remove();
        }
    }).mouseup(function() {
        if (currentDragged) {
            $('.tempTrayItem').removeClass('tempTrayItem');
            $(this).removeClass('ui-state-highlight');
            var settings = db.open('-settings');
            if (!settings) {
                settings = {
                    _id:"-settings",
                    tray:["Person","Project","Action_Item"]
                };
            }
            if (settings.tray) {
                settings.tray.push(currentDragged);
                db.save(settings);
            }



            currentDragged = null;
        }
    })
}





wikid.toTagList = function(tags) {
    var tag_links = [];
	if (tags) {
		for (var i in tags) {
			var tag = tags[i];
			var link = this.getTagLink(tag);
			tag_links.push(link);
		}
	}
	return tag_links;
}

wikid.findPublicFields = function(doc) {
	var publicFields = [];
    var wikid = this;
	jQuery.each(doc, function(i, val) {
		if (i[0] != '-' && i[0] != '_') {
			var field = {};
			field.id = i;
			field.name = wikid.titleFromTopicId(i);
			field.value = val;
			publicFields.push(field);
		}
	});
	return publicFields;
}

wikid.findPublicAttachments = function(doc) {
	var publicAttachments = [];
	if (!doc['_attachments']) return publicAttachments;
	jQuery.each(doc['_attachments'], function(i, val) {
		if (i[0] != '-' && i[0] != '_') {
			publicAttachments.push({'name': i, 'val': val});
		}
	});
	return publicAttachments;
}


wikid.getFreebaseLink = function(doc) {
    if (!doc['-freebase_id']) return null;
    var fbid = encodeURIComponent(doc['-freebase_id']);
    return "http://www.freebase.com/private/flyout?id=" + fbid;
}

wikid.getFacebookDetails = function(doc) {
    if (!doc['-facebook_id']) return null;
    var details = {};
    details.graphUrl = "http://graph.facebook.com/" + doc['-facebook_id'];
    details.picture = details.graphUrl + "/picture";
    return details;
}




wikid.getDocumentLinksForTag = function(tag, db) {
	var tag_links = [];
	var tagged = db.view("system/doc_by_tag", {key : tag});
	
	if (!tagged || !tagged.rows ) {
		return null;
	}
	var wikid = this;
	jQuery.each(tagged.rows, function(i, val) {
		var tag = val.value;
		var link = wikid.getTagLink(tag);
		tag_links.push(link);
	});
	return tag_links;
}

wikid.generatePathLinks = function(path) {
	var tag_links = [];
	for (var i in path) {
		var tag = path[i];
		var link = this.getTagLink(tag);
		tag_links.push(link);		
	}
	return tag_links;
}


wikid.loadTagInstanceInfos = function(tags, db) {
	var instanceInfos = {};
	var instances = db.view("system/tag_to_instanceInfo",{},tags);
	if (!instances || !instances.rows ) return null;
	for (var i in instances.rows) {
		var instance = instances.rows[i];
		instanceInfos[instance.key] = instance.value;
	}
	return instanceInfos;
}

wikid.addTags = function(result, tags, db) {
	if (!tags) return;
	if (result.doc['-tags']) {
		jQuery.merge(result.doc['-tags'], tags);
	
	}  else {
		result.doc['-tags'] = tags;
		result.instanceInfos = this.loadTagInstanceInfos(result.doc['-tags'], db);
	}
	
}

wikid.documentTitle = function(readableTopic) {
    return readableTopic + ' - ECKO IT';
}

wikid.toWikid = function(doc, db, mode) {
	var result = {};
    result.db = db;
	result.db_info = db.info();
	result.doc = doc;
	result.topic = this.titleFromTopicId(doc._id);
	result.title = this.documentTitle(result.topic);
	if (doc['-wiki']) {
		result.wiki = this.wikiTextToHtml(doc['-wiki'], doc, db.name);
	}
	if (doc['-path']) {
		result.path = this.generatePathLinks(doc['-path']);
	}
	result.fields = this.findPublicFields(doc);
	if (db) 
		result.tagged = this.getDocumentLinksForTag(doc._id, db);
	
	if (doc['-tags']) {
		//console.log('tags!');
		result.tags = this.toTagList(doc['-tags']);
		//console.log('result tags: ', result.tags);
		if (db) {
			//console.log('db');
			result.instanceInfos = this.loadTagInstanceInfos(result.doc['-tags'], db);
			//console.log('instance infos: ', result.instanceInfos);
		}
		result.menu = this.generateInstanceMenu(result);
		this.loadInstanceScripts(result, 'scripts', mode);
	}	
	
	result.attachments = this.findPublicAttachments(doc);
    result.freebaseLink = this.getFreebaseLink(doc);
    result.facebookDetails = this.getFacebookDetails(doc);

	return result;
}

wikid.loadInstanceScripts = function(result, scriptBase, mode) {
	if (!result.instanceInfos) return [];
	for (var tag in result.instanceInfos) {
		var instanceInfo = result.instanceInfos[tag];
		if (instanceInfo.script) {
			// get the tag script
			// http://localhost:5984/wikid/Project/Project.js
			var wikid = this;
			var url = scriptBase + "/" + tag + "/" + tag + ".js";
			$.getScript(url, function() {
                wikid.deferredTagCall(tag, mode, result);
			});
		}
	}
}

wikid.deferredTagCall = function (tag, mode, result) {
    var timeoutId = null;
    var defFuc = function() {
        if (wikid[tag] && wikid[tag][mode]){
            wikid[tag][mode](result);
            if (timeoutId) clearInterval(timeoutId);
        }
    }
    timeoutId = setInterval(defFuc, 100);
}


wikid.registerGenerateTopicId = function(tag, topicIdFunction) {

    var newTopicLocation = $('#field_editor_wrap').parent();
    $('#topicEntry').appendTo(newTopicLocation);


    $('#title').text('New ' + tag);
    $('.jeclass').live('blur', function() {
       var topic_id =  topicIdFunction();
        var title = wikid.titleFromTopicId(topic_id);
        $('#title').text(title);
        $('#wikid_id').val(topic_id);
    });
}



wikid.generateInstanceMenu = function(result) {
	var menu = {};
	menu.add = [];
	menu.tools = [];
	if (!result.instanceInfos) return [];
	for (var tag in result.instanceInfos) {
		var instanceInfo = result.instanceInfos[tag];
		if (instanceInfo['-instance'] && instanceInfo['-instance'].addmenu) {
			var item = this.generateAddMenu(instanceInfo['-instance'].addmenu, result);
			menu.add.push(item);
		}
		if (instanceInfo['-instance'] && instanceInfo['-instance'].toolsmenu) {
			var item = this.generateToolsMenu(instanceInfo['-instance'].toolsmenu, result);
			//console.dir(item);
			menu.tools.push(item);
		}
	}
	return menu;	
}



wikid.generateToolsMenu = function(obj, result) {
	var menu = {};
	for (name in obj) {
		menu.name = name;
		var val = obj[name];
		//console.dir(val);
		menu.url = this.compoundPathString(val, result);
	}		
	return menu;
}



wikid.generateAddMenu = function(obj, result) {
	var menu = {};
	for (name in obj) {
		menu.name = name;
		menu.tags = [];
		var val = obj[name];
		if (val && val.tags) {
			for (var j in val.tags) {
				var tag = val.tags[j];
				var tag_str = this.compoundPathString(tag, result);
				menu.tags.push(tag_str);
			}
		}
	}
	return menu;
}

wikid.compoundPathString = function(compoundPathString, obj) {
	var type = typeof compoundPathString;
	if ($.isArray(compoundPathString)) {
		var str = '';
		for (var i in compoundPathString) {
			var calculated = this.compoundPathString(compoundPathString[i], obj);
			str = str + calculated;
		}
		return str;
	}
	if (type === 'string') {
		return compoundPathString; 
	}
	if (type === 'object') {
		var ew = jsonPath(obj, compoundPathString.jsonPath);
		return ew;
	}
}


wikid.findRecentChangesByDate = function(db, limit) {
	if (!limit) limit = 20;
	var results = db.view("system/changes_by_date", {limit : limit, descending:true});
	if (!results || !results.rows ) return null;
	
	var newDateHolder = function() {
		var dateHolder = {};
		dateHolder.date = null;
		dateHolder.links = [];
		return dateHolder;
	}
	
	var wikid = this;
	var dates = [];
	var dateHolder = newDateHolder();

	for (var i in results.rows) {
		var row = results.rows[i];
		if (dateHolder.date != row.key) {
			dateHolder = newDateHolder();
			dateHolder.date = row.key;
			dates.push(dateHolder);
		}
		var link = wikid.getTagLink(row.id);
		dateHolder.links.push(link);
	};
	return dates;
}

wikid.runTagScripts = function(doc) {
	


}

wikid.findSpaces = function() {
    var spaces = [];
    // load all the spaces
    var all = CouchDB.allDbs();
    $.each(all, function(i, val) {
       if (val[0] != '-' && val[0] != '_' && !(/_$/.test(val))) {
           spaces.push(val);
       }
    });
    return spaces;
}


wikid.findAllTopics = function(db) {
    var topics = [];
    var result = db.allDocs();
    $.each(result.rows, function(i,doc) {
        if (doc.id[0] != '-' && doc.id[0] != '_') {
            var topic = {};
            topic.id = doc.id;
            topic.title = wikid.titleFromTopicId(topic.id);
            topics.push(topic);
        }
    });
    return topics;
}



// wikid.instanceAddMenuTags = function(code, doc) {
	// // we probably should clone the doc?
  	// JSandbox.eval(
		// code, 
		// function(r) { 
			// // r should be an array
		// },
		// doc,
		// function(err) {
			// // there was a problem
		// }
	// );
// }


     function _renderValue(value) {
        function isNullOrEmpty(val) {
          if (val == null) return true;
          for (var i in val) return false;
          return true;
        }
        function render(val) {
          var type = typeof(val);
          if (type == "object" && !isNullOrEmpty(val)) {
            var list = $("<dl></dl>");
            for (var i in val) {
              $("<dt></dt>").text(i).appendTo(list);
              $("<dd></dd>").append(render(val[i])).appendTo(list);
            }
            return list;
          } else {
            var html = $.futon.formatJSON(val, {
              html: true,
              escapeStrings: false
            });
            return $(html);
          }
        }
        var elem = render(value);

        elem.find("dd:has(dl)").hide().prev("dt").addClass("collapsed");
        elem.find("dd:not(:has(dl))").addClass("inline").prev().addClass("inline");
        elem.find("dt.collapsed").click(function() {
          $(this).toggleClass("collapsed").next().toggle();
        });

        return elem;
      }
      
      
      
var zeropad = function(num) {
	return ((num < 10) ? '0' : '') + num;
}

var iso8601 = function (date) {
	return date.getUTCFullYear() 
	 + "-" + zeropad(date.getUTCMonth()+1)
	 + "-" + zeropad(date.getUTCDate())
	 + "T" + zeropad(date.getUTCHours())
	 + ":" + zeropad(date.getUTCMinutes())
	 + ":" + zeropad(date.getUTCSeconds()) + "Z";
}      


// ui stuff
wikid.ui = wikid.ui || {};

wikid.ui.showTag = function(contentDiv, tag, pps) {
	this.creatOuterTagDiv(contentDiv, tag, pps);
}


wikid.ui.creatOuterTagDiv = function(contentDiv, tagId, label, start, duration, pps) {
	var marginLeft = this.calculateSecondsPixelSize(start, pps);
	var width = this.calculateSecondsPixelSize(duration, pps);
	//var div = $('<div id="tag-'+ tagId +'" class="tagholder"><div class="streambar"></div><span class="tagtopic">' + text + '</span><div class="tagContent">This is the content and it is really long</div></div>');
	var div = $('<div id="tag-'+ tagId +'"  class="tagholder"><div class="streambar"></div><span class="tagtopic">' + label + '</span></div>');
	div.css('margin-left', marginLeft + 'px');
	div.width(width);
	
	div.find(".streambar").css({'width' : width + 'px'});
	div.find(".tagContent").css({'width' : width + 'px'});
	contentDiv.append(div);
	var tagTopic = div.find(".tagtopic");
	
	var textRight = tagTopic.width() +  5;
	tagTopic.css({'right' : '-' + textRight +'px'});	
}

wikid.ui.creatInnerTagDiv = function(parentTagId, contentOffset, tagId, text, start, pps) {
	var parent = $('#tag-' + parentTagId);
	var parentPixalOffset = parent.offset().left - contentOffset;
	var marginLeft = this.calculateSecondsPixelSize(start, pps) - parentPixalOffset;
	parent.append($('<li id="tag-'+ tagId +'" class="tagContent">' + text + '</li>'))
	$('#tag-'+ tagId).css('margin-left', marginLeft + 'px');
}

wikid.ui.createInnerTopic = function(parentTagId, contentOffset, tagId, label, start, duration, pps) {
	var parent = $('#tag-' + parentTagId);
	
	var topicLevel = this.calculateTagDepth(parent);
	//console.log(topicLevel);
	
	var parentPixalOffset = parent.offset().left - contentOffset;
	var marginLeft = this.calculateSecondsPixelSize(start, pps) - parentPixalOffset;
	var width = this.calculateSecondsPixelSize(duration, pps);
	var div = $('<div id="tag-'+ tagId +'"  class="tagholder"><div class="streambar"></div><span class="tagtopic">' + label + '</span></div>');
	div.css('margin-left', marginLeft + 'px');
	div.addClass('tagholder-level' + topicLevel);
	div.width(width);
	
	div.find(".streambar").css({'width' : width + 'px'});
	div.find(".tagContent").css({'width' : width + 'px'});
	parent.append(div);
	var tagTopic = div.find(".tagtopic");
	
	var textRight = tagTopic.width() +  5;
	tagTopic.css({'right' : '-' + textRight +'px'});
}


wikid.ui.createTimeBand = function(div, pps, duration) {
	var band = $('<div id="timeband"></div>');
	div.append(band);
	var width = band.width();
	var minuteSpacingWithBorders = Math.floor(60 * pps);
	var minuteSpacing = Math.floor(59 * pps);
	var divsNeeded = Math.round(duration / minuteSpacingWithBorders);
	var total = divsNeeded * minuteSpacingWithBorders;
	
	for (var i =0; i < divsNeeded; i++) {
		var marker = $('<div class="marker" style="width: ' + minuteSpacing +'px;"></div>');
		band.append(marker);
	}
	band.find('.marker:nth-child(10n)').addClass('markerTenMinute').each(function(i){
		var time = (i+1) * 10;
		var label = $('<div class="timelabel">'+ time + 'm</div>');
		$(this).append(label);

		
	});
	band.find('.marker:nth-child(60n)').addClass('markerHour');
}


wikid.ui.calculateTagDepth = function(parent) {
	if (!parent.hasClass('tagholder')) return 1;
	else {
		var nextParent = parent.parent();
		return 1 + this.calculateTagDepth(nextParent);
	}
}




wikid.ui.calculateSecondsPixelSize = function(seconds, pps) {
	var result =  Math.round(seconds * pps);
	if (!result) return 1;
	return result;
}


wikid.ui.createInnerTagDiv = function(div, tag) {

}


wikid.ui.calculatePixelsPerSecond = function(divWidth, audioDuration, zoom ) {
	if (!zoom) zoom = 1;
	return divWidth / (audioDuration * zoom);
} 




wikid.getAudioInfo = function(doc) {
    return doc.media;
}


wikid.getAudioInfo = function(doc) {
    return doc.media;
}




